/**
 * @author karlwang
 * @Time：2018年7月20日 下午5:36:46
 * @version 1.0  
 */
package com.len.core.filter;
 
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.len.rule.RolePermRule;
import com.len.service.MenuService;
import com.len.service.SysUserService;
import com.len.util.ApplicationContextUtil;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.Filter;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/* *
 * @Author karlwang
 * @Description Filter 管理器过滤链
 * @Date 11:16 2018/2/28
 */
@Component
@Slf4j
public class ShiroFilterChainManager {

    private final MenuService menuService ;
    private final StringRedisTemplate redisTemplate;
    private final SysUserService sysUserService;

    @Autowired
    public ShiroFilterChainManager(MenuService menuService,StringRedisTemplate redisTemplate,SysUserService sysUserService){
        this.menuService = menuService;
        this.redisTemplate = redisTemplate;
        this.sysUserService = sysUserService;
    }

    // 初始化获取过滤链
    public Map<String,Filter> initGetFilters() {
        Map<String,Filter> filters = new LinkedHashMap<>();
        PasswordFilter passwordFilter = new PasswordFilter();
        passwordFilter.setRedisTemplate(redisTemplate);
        filters.put("auth",passwordFilter);
        BJwtFilter jwtFilter = new BJwtFilter();
        jwtFilter.setRedisTemplate(redisTemplate);
        jwtFilter.setSysUserService(sysUserService);
        filters.put("jwt",jwtFilter);
        VerfityCodeFilter vf= new VerfityCodeFilter();
        vf.setFailureKeyAttribute("shiroLoginFailure");
        vf.setJcaptchaParam("code");
        vf.setVerfitiCode(true);
        filters.put("verCode",vf);
        log.info("初始化获取过滤链");
        return filters;
    }
    // 初始化获取过滤链规则
    public Map<String,String> initGetFilterChain() {
        Map<String,String> filterChain = new LinkedHashMap<>();
        // -------------anon 默认过滤器忽略的URL
        List<String> defalutAnon = Arrays.asList("/css/**","/js/**");
        defalutAnon.forEach(ignored -> filterChain.put(ignored,"anon"));
        // -------------auth 默认需要认证过滤器的URL 走auth--PasswordFilter
        List<String> defalutAuth = Arrays.asList("/account/**");
        defalutAuth.forEach(auth -> filterChain.put(auth,"auth"));
        // -------------dynamic 动态URL
        if (menuService != null) {
            List<RolePermRule> rolePermRules = this.menuService.selectRolePermRule();
            if (null != rolePermRules) {
                rolePermRules.forEach(rule -> {
                    StringBuilder Chain = rule.toFilterChain();
                    if (null != Chain) {
                        filterChain.putIfAbsent(rule.getUrl(),Chain.toString());
                    }
                });
            }
        }
        filterChain.put("/login","verCode,anon");
        //filterMap.put("/login","anon");
        filterChain.put("/getCode","anon");
        filterChain.put("/blog/**","anon");
        filterChain.put("/logout","logout");
        filterChain.put("/plugin/**","anon");
        filterChain.put("/loginSubmit/**","auth");
        return filterChain;
    }
    // 动态重新加载过滤链规则
    public void reloadFilterChain() {
            ShiroFilterFactoryBean shiroFilterFactoryBean = ApplicationContextUtil.getBean(ShiroFilterFactoryBean.class);
            AbstractShiroFilter abstractShiroFilter = null;
            try {
                abstractShiroFilter = (AbstractShiroFilter)shiroFilterFactoryBean.getObject();
                RestPathMatchingFilterChainResolver filterChainResolver = (RestPathMatchingFilterChainResolver)abstractShiroFilter.getFilterChainResolver();
                DefaultFilterChainManager filterChainManager = (DefaultFilterChainManager)filterChainResolver.getFilterChainManager();
                filterChainManager.getFilterChains().clear();
                shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
                shiroFilterFactoryBean.setFilterChainDefinitionMap(this.initGetFilterChain());
                shiroFilterFactoryBean.getFilterChainDefinitionMap().forEach((k,v) -> filterChainManager.createChain(k,v));
            }catch (Exception e) {
                log.error(e.getMessage(),e);
            }
    }
}